package com.gzhryc.shared_device.oem.micro.api.controllers.callback;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.time.DateUtils;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.kafka.JFKafkaProducer;
import com.gzhryc.common.kafka.KafkaProducerFactory;
import com.gzhryc.common.kafka.models.KafkaMessage;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.pay.adaptation.weixin.DefaultWXPayConfig;
import com.gzhryc.pay.adaptation.weixin.WXPayUtils;
import com.gzhryc.pay.adaptation.weixin.enums.EWXPayAdvanceNotifyType;
import com.gzhryc.pay.adaptation.weixin.msg.WXPayNotify;
import com.gzhryc.pay.adaptation.weixin.msg.WXPayNotifyResponse;
import com.gzhryc.pay.adaptation.weixin.msg.advance_pay.WXPayAdvancePayConfirmNotify;
import com.gzhryc.pay.adaptation.weixin.msg.advance_pay.WXPayAdvancePayFinishNotify;
import com.gzhryc.pay.adaptation.weixin.msg.advance_pay.WXPayAdvancePayNotify;
import com.gzhryc.pay.adaptation.weixin.msg.normal.WXPayNormalPayNotify;
import com.gzhryc.pay.adaptation.weixin.msg.normal.WXPayNormalRefundNotify;
import com.gzhryc.servlet.WebUtils;
import com.gzhryc.servlet.annotation.Route;
import com.gzhryc.shared_device.base.enums.EOperatorType;
import com.gzhryc.shared_device.base.enums.ERefundState;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNOrder;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNShopOrder;
import com.gzhryc.shared_device.bxscn.code.services.BXSCNOrderService;
import com.gzhryc.shared_device.bxscn.code.services.BXSCNShopOrderService;
import com.gzhryc.shared_device.cdb.code.dao.db.CDBOrder;
import com.gzhryc.shared_device.cdb.code.services.CDBOrderService;
import com.gzhryc.shared_device.cdcz.code.dao.db.CDCZOrder;
import com.gzhryc.shared_device.cdcz.code.services.CDCZOrderService;
import com.gzhryc.shared_device.common.payment.dao.db.WXRefundOrder;
import com.gzhryc.shared_device.common.payment.services.WXRefundOrderService;
import com.gzhryc.shared_device.oem.code.KafkaEventConstants;
import com.gzhryc.shared_device.oem.code.PayServiceFactory;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.member.services.MemberBusinessOrderService;
import com.gzhryc.shared_device.oem.code.member.services.MemberRechargeOrderService;
import com.gzhryc.shared_device.oem.code.order.event.OrderCancelEvent;
import com.gzhryc.shared_device.oem.code.order.event.OrderFinishEvent;
import com.gzhryc.shared_device.oem.code.order.event.OrderRefundEvent;
import com.gzhryc.shared_device.oem.micro.api.MicroConstants;
import com.gzhryc.shared_device.oem.micro.api.OrderCollectManager;
import com.gzhryc.shared_device.pcl.code.dao.db.PCLOrder;
import com.gzhryc.shared_device.pcl.code.services.PCLOrderService;

public class WXPayCallbackController {

	static Logger log = Logger.getLogger(WXPayCallbackController.class);

	@Route(value = {"/paycall/wxpay/{appId}/{busiType}/pay","/paycall/{busiType}/wxpay/{appId}/pay"})
	public WXPayNotifyResponse wxpay(HttpServletRequest request, HttpServletResponse response) {
		String appId = WebUtils.getString(request, "appId");
		String busiType = WebUtils.getString(request,"busiType",EBusinessType.CDCZ.index());
		WXPayNotify notify = null;
		try {
			notify = WebUtils.getJsonRequest(request, WXPayNotify.class);
			log.info("{{0}}微信普通支付回调，回调内容：{{1:json}}", appId, notify);
			DefaultWXPayConfig config = PayServiceFactory.self().getWXPayConfig(appId, busiType.toUpperCase());
			if (config != null && notify != null) {
				WXPayNormalPayNotify payNotify = WXPayUtils.getWXPayNormalPayNotify(notify, config);
				if(payNotify != null) {
					OperateInfo operateInfo = new OperateInfo(MicroConstants.PROGRAM_TYPE,MicroConstants.PROGRAM_TYPE_NAME);
					operateInfo.setOperator(EOperatorType.System.index(),"微信支付回调接口");
					operateInfo.setOperateNote("微信支付回调");
					OrderCollectManager.payResult(payNotify, operateInfo);
				}else {
					log.error("{{0}}微信回调解析失败", appId);
				}
			}
		} catch (Exception e) {
			log.error(appId + "微信支付回调错误，" + e.getMessage(), e);
		}
		return new WXPayNotifyResponse();
	}

	@Route(value = {"/paycall/wxpay/{appId}/{busiType}/refund","/paycall/{busiType}/wxpay/{appId}/refund"})
	public WXPayNotifyResponse refund(HttpServletRequest request, HttpServletResponse response) {
		String appId = WebUtils.getString(request, "appId");
		String busiType = WebUtils.getString(request,"busiType",EBusinessType.CDCZ.index());
		WXPayNotify notify = null;
		try {
			notify = WebUtils.getJsonRequest(request, WXPayNotify.class);
			log.info("{{0}}微信普通退款回调，回调内容：{{1:json}}", appId, notify);
			DefaultWXPayConfig config = PayServiceFactory.self().getWXPayConfig(appId, busiType.toUpperCase());
			if (notify != null && config != null) {
				WXPayNormalRefundNotify refundNotify = WXPayUtils.getWXPayNormalRefundNotify(notify, config);
				Date currentDate = new Date();
				WXRefundOrder refundOrder = WXRefundOrderService.self(currentDate).refundResult(refundNotify);
				if(refundOrder == null){
					//查询上一年订单
					currentDate = DateUtils.addYears(currentDate,-1);
					refundOrder = WXRefundOrderService.self(currentDate).refundResult(refundNotify);
				}
				if (refundOrder != null) {
					OperateInfo operateInfo = new OperateInfo(MicroConstants.PROGRAM_TYPE, MicroConstants.PROGRAM_TYPE_NAME);
					operateInfo.setOperator(EOperatorType.System.index(), "微信退款回调接口");
					
					if (EBusinessType.RECHARGE.index().equals(refundOrder.getBusinessType())) {
						operateInfo.setOperateNote("微信充值退款回调");
						//处理
						MemberRechargeOrderService.self(refundOrder.getCreateDate()).refundResult(refundOrder, operateInfo);
					}else {
						operateInfo.setOperateNote("微信退款回调");
						if (ERefundState.Success.index().equals(refundOrder.getRefundStatus())) {
							int result = -1;
							Long money = null;
							Integer payMoney = null;
							Long walletMoney = null;
							if (EBusinessType.CDCZ.index().equals(refundOrder.getBusinessType())) {
								result = CDCZOrderService.self(new Date()).refundSuccess(refundOrder, operateInfo);
								CDCZOrder deviceOrder = CDCZOrderService.self(new Date()).getByTradeNo(refundOrder.getBusinessTradeNo());
								money = deviceOrder.getMoney();
								payMoney = deviceOrder.getPayMoney();
								walletMoney = deviceOrder.getWalletMoney();
							} else if (EBusinessType.CDB.index().equals(refundOrder.getBusinessType())) {
								result = CDBOrderService.self(new Date()).refundSuccess(refundOrder, operateInfo);
								CDBOrder deviceOrder = CDBOrderService.self(new Date()).getByTradeNo(refundOrder.getBusinessTradeNo());
								money = deviceOrder.getMoney();
								payMoney = deviceOrder.getPayMoney();
								walletMoney = deviceOrder.getWalletMoney();
							} else if (EBusinessType.BXSCN.index().equals(refundOrder.getBusinessType())) {
								result = BXSCNOrderService.self(new Date()).refundSuccess(refundOrder, operateInfo);
								BXSCNOrder deviceOrder = BXSCNOrderService.self(new Date()).getByTradeNo(refundOrder.getBusinessTradeNo());
								money = deviceOrder.getMoney();
								payMoney = deviceOrder.getPayMoney();
								walletMoney = deviceOrder.getWalletMoney();
							} else if (EBusinessType.BXSCN_SHOP.index().equals(refundOrder.getBusinessType())) {
								result = BXSCNShopOrderService.self(new Date()).refundSuccess(refundOrder, operateInfo);
								BXSCNShopOrder bxscnShopOrder = BXSCNShopOrderService.self(new Date()).getByTradeNo(refundOrder.getBusinessTradeNo());
								money = bxscnShopOrder.getMoney();
								payMoney = bxscnShopOrder.getPayMoney();
								walletMoney = bxscnShopOrder.getWalletMoney();
							}else if (EBusinessType.PCL.index().equals(refundOrder.getBusinessType())) {
								result = PCLOrderService.self(new Date()).refundSuccess(refundOrder, operateInfo);
								PCLOrder deviceOrder = PCLOrderService.self(new Date()).getByTradeNo(refundOrder.getBusinessTradeNo());
								money = deviceOrder.getMoney();
								payMoney = deviceOrder.getPayMoney();
								walletMoney = deviceOrder.getWalletMoney();
							} else {
								log.error("微信普通退款回调未知的业务类型，退款订单：{{0:json}}", refundOrder);
							}
	
							log.info("{{0}}订单退款处理结果：{{1}}",refundOrder.getBusinessTradeNo(),result);
	
							//同步会员订单
							if (result == 1) {
								MemberBusinessOrderService.self(refundOrder.getCreateDate()).cancel(refundOrder.getBusinessTradeNo(),money,payMoney,walletMoney);
							} else if (result == 2) {
								MemberBusinessOrderService.self(refundOrder.getCreateDate()).refundMoney(refundOrder.getBusinessTradeNo(), refundOrder.getRefundMoney());
							} else if (result == 3) {
								MemberBusinessOrderService.self(refundOrder.getCreateDate()).finish(refundOrder.getBusinessTradeNo(),money, payMoney, walletMoney,operateInfo);
							} else {
								log.error("微信普通退款回调充电宝订单处理失败，退款订单：{{0:json}}", refundOrder);
							}
	
							JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
							if (producer != null) {
								if (result == 1) {
									OrderCancelEvent event = new OrderCancelEvent(refundOrder.getBusinessType(), refundOrder.getBusinessTradeNo()
											,refundOrder.getCreateDate(),NumberTools.changeMoneyLi(NumberTools.changeMoney(refundOrder.getRefundMoney())),new Date());
									KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_OrderCancel,JsonTools.toJson(event));
									producer.send(kafkaMessage);
								} else if (result == 2) {
									Long refundMoney = NumberTools.changeMoneyLi(NumberTools.changeMoney(refundOrder.getRefundMoney()));
									OrderRefundEvent event = new OrderRefundEvent(refundOrder.getBusinessType(), refundOrder.getBusinessTradeNo(),new Date()
											,refundMoney,refundOrder.getRefundDate());
									KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_OrderRefund,JsonTools.toJson(event));
									producer.send(kafkaMessage);
								} else if (result == 3) {
									OperateInfo temp = ClassTools.copy(new OperateInfo(), operateInfo);
									OrderFinishEvent event = new OrderFinishEvent(refundOrder.getBusinessType(), refundOrder.getBusinessTradeNo(), new Date(), temp);
									KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_OrderFinish, JsonTools.toJson(event));
									producer.send(kafkaMessage);
								}
							}else{
								log.error("未初始化消息队列");
							}
						} else {
							if (EBusinessType.CDCZ.index().equals(refundOrder.getBusinessType())) {
								CDCZOrderService.self(new Date()).refundFail(refundOrder, operateInfo);
							} else if (EBusinessType.CDB.index().equals(refundOrder.getBusinessType())) {
								CDBOrderService.self(new Date()).refundFail(refundOrder, operateInfo);
							}else if (EBusinessType.BXSCN.index().equals(refundOrder.getBusinessType())) {
								BXSCNOrderService.self(new Date()).refundFail(refundOrder, operateInfo);
							}else if (EBusinessType.BXSCN_SHOP.index().equals(refundOrder.getBusinessType())) {
								BXSCNShopOrderService.self(new Date()).refundFail(refundOrder, operateInfo);
							}else if (EBusinessType.PCL.index().equals(refundOrder.getBusinessType())) {
								PCLOrderService.self(new Date()).refundFail(refundOrder, operateInfo);
							}
						}
					}
				} else {
					log.error("微信普通退款回调未找到退款订单，回调内容：{{0:json}}", notify);
				}
			} else {
				log.error("未获取{{0}}的微信配置或空回调信息", appId);
			}
		} catch (Exception e) {
			log.error(appId + "微信退款回调错误，" + e.getMessage(), e);
		}
		return new WXPayNotifyResponse();
	}

	/**
	 * 微信支付免押通用回调：/paycall/wxpay/{appId}/{busiType}/rentbill
	 * @param request
	 * @param response
	 */
	@Route(value = {"/paycall/wxpay/{appId}/{busiType}/rentbill","/paycall/{busiType}/wxpay/{appId}/rentbill"})
	public WXPayNotifyResponse rentBill(HttpServletRequest request, HttpServletResponse response) {
		String appId = WebUtils.getString(request, "appId");
		String busiType = WebUtils.getString(request,"busiType",EBusinessType.CDCZ.index());
		OperateInfo operateInfo = new OperateInfo(MicroConstants.PROGRAM_TYPE, MicroConstants.PROGRAM_TYPE_NAME);
		operateInfo.setOperator(EOperatorType.System.index(), "微信免押回调接口");
		try {
			WXPayAdvancePayNotify notify = WebUtils.getJsonRequest(request,WXPayAdvancePayNotify.class);
			DefaultWXPayConfig config = PayServiceFactory.self().getWXPayConfig(appId,busiType.toUpperCase());
			if(EWXPayAdvanceNotifyType.USER_CONFIRM.index().equals(notify.getEvent_type())){
				WXPayAdvancePayConfirmNotify confirmNotify = WXPayUtils.getWXPayAdvancePayConfirmNotify(notify,config);
				log.info("微信免押用户确定回调，APPID：{{0}}，回调内容：{{1:json}}", appId, confirmNotify);
				
				operateInfo.setOperateNote("微信支付分用户确认");
				
				OrderCollectManager.payResult(confirmNotify, operateInfo);
				
			}else if(EWXPayAdvanceNotifyType.USER_PAID.index().equals(notify.getEvent_type())){
				WXPayAdvancePayFinishNotify finishNotify = WXPayUtils.getWXPayAdvancePayFinishNotify(notify,config);
				log.info("微信免押支付成功回调，APPID：{{0}}，回调内容：{{1:json}}", appId, finishNotify);
				
				operateInfo.setOperateNote("微信免押支付成功");
				
				OrderCollectManager.payResult(finishNotify, operateInfo);
				
			}
		} catch (Exception e) {
			log.error(appId + "微信免押回调错误", e);
		}
		return new WXPayNotifyResponse();
	}
}
